﻿#include "QuestDialogs.h"
#include "../../MirGraphics/MLibrary.h"
#include "../GameScene.h"
#include "../../MirSounds/SoundManager.h"
#include "../../MirObjects/MapObject.h"
#include "../../MirObjects/NPCObject.h"
#include "../../../Shared/Globals.h"
#include "../../Forms/Client.CMain.h"
#include "../../../Shared/Functions/Functions.h"
#include "../../../Shared/Enums.h"

using namespace Client::MirControls;
using namespace Client::MirGraphics;
using namespace Client::MirNetwork;
using namespace Client::MirObjects;
using namespace Client::MirSounds;
namespace S = ServerPackets;
namespace C = ClientPackets;

namespace Client::MirScenes::Dialogs
{

    QuestListDialog::QuestListDialog()
    {
        setIndex(950);
        setLibrary(Libraries::Prguse);
        setMovable(true);
        setSort(true);
        Point tempVar(GameScene::Scene->NPCDialog->getSize()->Width + 47, 0);
        setLocation(&tempVar);

        MirImageControl *TitleLabel = new MirImageControl();
        TitleLabel->setIndex(14);
        TitleLabel->setLibrary(Libraries::Title);
        Point tempVar2(18, 9);
        TitleLabel->setLocation(&tempVar2);
        TitleLabel->setParent(this);

        #pragma region QuestSelection

        MirButton *upQuestButton = new MirButton();
        upQuestButton->setIndex(951);
        upQuestButton->setHoverIndex(952);
        upQuestButton->setPressedIndex(953);
        upQuestButton->setLibrary(Libraries::Prguse);
        upQuestButton->setParent(this);
        Point tempVar3(291, 35);
        upQuestButton->setLocation(&tempVar3);
        upQuestButton->setSound(SoundList::ButtonA);
        upQuestButton->Click += [&] (o, e)
        {
            if (SelectedQuest != nullptr)
            {
                SelectedIndex = FindSelectedIndex();
    
                if (SelectedIndex > 0)
                {
                    SelectedIndex--;
                }
                else
                {
                    StartIndex--;
                }
            }
    
            RefreshInterface();
        };

        MirButton *downQuestButton = new MirButton();
        downQuestButton->setIndex(957);
        downQuestButton->setHoverIndex(958);
        downQuestButton->setPressedIndex(959);
        downQuestButton->setLibrary(Libraries::Prguse);
        downQuestButton->setParent(this);
        Point tempVar4(291, 83);
        downQuestButton->setLocation(&tempVar4);
        downQuestButton->setSound(SoundList::ButtonA);
        downQuestButton->Click += [&] (o, e)
        {
            if (SelectedQuest != nullptr)
            {
                SelectedIndex = FindSelectedIndex();
    
                if (SelectedIndex < Rows.size() - 1)
                {
                    SelectedIndex++;
                }
                else
                {
                    StartIndex++;
                }
            }
    
            RefreshInterface();
        };
        #pragma endregion

        #pragma region Buttons

        _acceptButton = new MirButton();
        _acceptButton->setIndex(270);
        _acceptButton->setHoverIndex(271);
        _acceptButton->setPressedIndex(272);
        _acceptButton->setLibrary(Libraries::Title);
        _acceptButton->setParent(this);
        Point tempVar5(40, 436);
        _acceptButton->setLocation(&tempVar5);
        _acceptButton->setSound(SoundList::ButtonA);
        _acceptButton->Click += [&] (o, e)
        {
            if (Reward == nullptr || SelectedQuest->Taken)
            {
                return;
            }
    
            C::AcceptQuest *tempVar6 = new C::AcceptQuest();
            tempVar6->NPCIndex = SelectedQuest->QuestInfo->NPCIndex;
            tempVar6->QuestIndex = SelectedQuest->QuestInfo->Index;
            Network::Enqueue(tempVar6);
            //Hide();

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar6' statement was not added since tempVar6 was passed to a method or constructor. Handle memory management manually.
        };

        _finishButton = new MirButton();
        _finishButton->setIndex(273);
        _finishButton->setHoverIndex(274);
        _finishButton->setPressedIndex(275);
        _finishButton->setLibrary(Libraries::Title);
        _finishButton->setParent(this);
        Point tempVar7(40, 436);
        _finishButton->setLocation(&tempVar7);
        _finishButton->setSound(SoundList::ButtonA);
        _finishButton->setVisible(false);
        _finishButton->Click += [&] (o, e)
        {
            if (Reward == nullptr || !SelectedQuest->Completed)
            {
                return;
            }
    
            if (Reward->SelectedItemIndex < 0 && SelectedQuest->QuestInfo->RewardsSelectItem.size() > 0)
            {
                MirMessageBox *messageBox = new MirMessageBox("You must select a reward item.");
                messageBox->Show();

            delete messageBox;
                return;

            delete messageBox;
            }
    
            C::FinishQuest *tempVar8 = new C::FinishQuest();
            tempVar8->QuestIndex = SelectedQuest->QuestInfo->Index;
            tempVar8->SelectedItemIndex = Reward->SelectedItemIndex;
            Network::Enqueue(tempVar8);
            //Hide();

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar8' statement was not added since tempVar8 was passed to a method or constructor. Handle memory management manually.
        };

        MirButton *leaveButton = new MirButton();
        leaveButton->setIndex(276);
        leaveButton->setHoverIndex(277);
        leaveButton->setPressedIndex(278);
        leaveButton->setLibrary(Libraries::Title);
        leaveButton->setParent(this);
        Point tempVar9(205, 436);
        leaveButton->setLocation(&tempVar9);
        leaveButton->setSound(SoundList::ButtonA);
        leaveButton->Click += [&] (o, e)
        {
            Hide();
        };

        #pragma endregion

        #pragma region Message Area

        MirButton *upButton = new MirButton();
        upButton->setIndex(197);
        upButton->setHoverIndex(198);
        upButton->setPressedIndex(199);
        upButton->setLibrary(Libraries::Prguse2);
        upButton->setParent(this);
        Size tempVar10(16, 14);
        upButton->setSize(&tempVar10);
        Point tempVar11(292, 136);
        upButton->setLocation(&tempVar11);
        upButton->setSound(SoundList::ButtonA);
        upButton->setVisible(true);

        MirButton *downButton = new MirButton();
        downButton->setIndex(207);
        downButton->setHoverIndex(208);
        downButton->setLibrary(Libraries::Prguse2);
        downButton->setPressedIndex(209);
        downButton->setParent(this);
        Size tempVar12(16, 14);
        downButton->setSize(&tempVar12);
        Point tempVar13(292, 282);
        downButton->setLocation(&tempVar13);
        downButton->setSound(SoundList::ButtonA);
        downButton->setVisible(true);

        MirButton *positionBar = new MirButton();
        positionBar->setIndex(205);
        positionBar->setHoverIndex(206);
        positionBar->setPressedIndex(206);
        positionBar->setLibrary(Libraries::Prguse2);
        Point tempVar14(292, 149);
        positionBar->setLocation(&tempVar14);
        positionBar->setParent(this);
        positionBar->setMovable(true);
        positionBar->setSound(SoundList::None);
        positionBar->setVisible(false);

        Message = new QuestMessage(upButton, downButton, positionBar, 10);
        Message->Font = new Font(Settings::FontName, 9.0F);
        Message->setParent(this);
        Size tempVar15(280, 160);
        Message->setSize(&tempVar15);
        Point tempVar16(10, 135);
        Message->setLocation(&tempVar16);
        Message->PosMinY = 149;
        Message->PosMaxY = 263;

        #pragma endregion

        #pragma region Rewards

        Reward = new QuestRewards();
        Reward->setParent(this);
        Reward->setVisible(false);
        Size tempVar17(313, 130);
        Reward->setSize(&tempVar17);
        Point tempVar18(5, 307);
        Reward->setLocation(&tempVar18);

        #pragma endregion

        _availableQuestLabel = new MirLabel();
        Font tempVar19(Settings::FontName, 8.0F);
        _availableQuestLabel->setFont(&tempVar19);
        _availableQuestLabel->setParent(this);
        _availableQuestLabel->setAutoSize(true);
        Point tempVar20(210, 8);
        _availableQuestLabel->setLocation(&tempVar20);

        MirButton *closeButton = new MirButton();
        closeButton->setIndex(360);
        closeButton->setHoverIndex(361);
        closeButton->setPressedIndex(362);
        closeButton->setLibrary(Libraries::Prguse2);
        closeButton->setParent(this);
        Point tempVar21(289, 3);
        closeButton->setLocation(&tempVar21);
        closeButton->setSound(SoundList::ButtonA);
        closeButton->Click += [&] (o, e)
        {
            Hide();
        };

        MirButton *helpButton = new MirButton();
        helpButton->setIndex(257);
        helpButton->setHoverIndex(258);
        helpButton->setPressedIndex(259);
        helpButton->setLibrary(Libraries::Prguse2);
        helpButton->setParent(this);
        Point tempVar22(266, 3);
        helpButton->setLocation(&tempVar22);
        helpButton->setSound(SoundList::ButtonA);
        helpButton->Click += [&] (o, e)
        {
            GameScene::Scene->HelpDialog->DisplayPage("Quests");
        };

        delete helpButton;
        delete closeButton;
//C# TO C++ CONVERTER TODO TASK: A 'delete positionBar' statement was not added since positionBar was passed to a method or constructor. Handle memory management manually.
//C# TO C++ CONVERTER TODO TASK: A 'delete downButton' statement was not added since downButton was passed to a method or constructor. Handle memory management manually.
//C# TO C++ CONVERTER TODO TASK: A 'delete upButton' statement was not added since upButton was passed to a method or constructor. Handle memory management manually.
        delete leaveButton;
        delete downQuestButton;
        delete upQuestButton;
        delete TitleLabel;
    }

    void QuestListDialog::Show()
    {
        if (getVisible())
        {
            return;
        }
        setVisible(true);

        CurrentNPCID = GameScene::NPCID;

        Reset();

        DisplayInfo();
    }

    void QuestListDialog::Hide()
    {
        if (!getVisible())
        {
            return;
        }
        setVisible(false);

        GameScene::Scene->NPCDialog->Hide();
    }

    void QuestListDialog::Toggle()
    {
        if (!getVisible())
        {
            Show();
        }
        else
        {
            Hide();
        }
    }

    void QuestListDialog::DisplayInfo()
    {
        if (!GetAvailableQuests())
        {
            Hide();
            return;
        }
        Reset();
        RefreshInterface();
    }

    void QuestListDialog::Reset()
    {
        StartIndex = 0;
        SelectedIndex = 0;
        SelectedQuest = nullptr;

        Message->setVisible(false);
        Reward->setVisible(false);

        for (int i = 0; i < Rows.size(); i++)
        {
            if (Rows[i] != nullptr)
            {
                Rows[i]->Dispose();
            }

            Rows[i] = nullptr;
        }
    }

    bool QuestListDialog::GetAvailableQuests()
    {
        NPCObject *npc = static_cast<NPCObject*>(MapControl::GetObject(CurrentNPCID));
        if (npc != nullptr)
        {
            Quests = npc->GetAvailableQuests();
        }

        return Quests.size() >= 1 && npc != nullptr;
    }

    void QuestListDialog::RefreshInterface()
    {
        _availableQuestLabel->setText(StringHelper::formatSimple("List: {0}", Quests.size()));

        int maxIndex = Quests.size() - Rows.size();

        if (StartIndex > maxIndex)
        {
            StartIndex = maxIndex;
        }
        if (StartIndex < 0)
        {
            StartIndex = 0;
        }

        for (int i = 0; i < Rows.size(); i++)
        {
            if (i >= Quests.size())
            {
                break;
            }

            if (Rows[i] != nullptr)
            {
                Rows[i]->Dispose();
            }

            QuestRow *tempVar = new QuestRow();
            tempVar->Quest = Quests[i + StartIndex];
            Point tempVar2(9, 36 + i * 19);
            tempVar->setLocation(&tempVar2);
            tempVar->setParent(this);
            Rows[i] = tempVar;
            Rows[i]->Click += [&] (o, e)
            {
                QuestRow *row = static_cast<QuestRow*>(o);
    
                if (row->Quest != SelectedQuest)
                {
                    SelectedQuest = row->Quest;
                    Reward->UpdateRewards(SelectedQuest);
                    Message->UpdateQuest(SelectedQuest);
                    SelectedIndex = FindSelectedIndex();
                    UpdateRows();
    
                    ReDisplayButtons();
                }
            };

            if (SelectedQuest != nullptr)
            {
                if (SelectedIndex == i)
                {
                    SelectedQuest = Rows[i]->Quest;
                    Reward->UpdateRewards(SelectedQuest);
                    Message->UpdateQuest(SelectedQuest);
                }
            }

            delete tempVar;
        }

        UpdateRows();

        ReDisplayButtons();
    }

    void QuestListDialog::UpdateRows()
    {
        if (SelectedQuest == nullptr)
        {
            if (Rows[0] == nullptr)
            {
                return;
            }

            SelectedQuest = Rows[0]->Quest;
            Reward->UpdateRewards(SelectedQuest);
            Message->UpdateQuest(SelectedQuest);
        }

        for (int i = 0; i < Rows.size(); i++)
        {
            if (Rows[i] == nullptr)
            {
                continue;
            }

            Rows[i]->Selected = false;

            if (Rows[i]->Quest == SelectedQuest)
            {
                Rows[i]->Selected = true;
            }

            Rows[i]->UpdateInterface();
        }
    }

    void QuestListDialog::ReDisplayButtons()
    {
        _acceptButton->setVisible(false);
        _finishButton->setVisible(false);

        if (Reward != nullptr)
        {
            Reward->setVisible(true);
            Message->setVisible(true);
        }

        if (SelectedQuest != nullptr)
        {
            if (!SelectedQuest->Taken && MapControl::getUser()->CurrentQuests.size() < Globals::MaxConcurrentQuests)
            {
                _acceptButton->setVisible(true);
            }

            if (SelectedQuest->Completed && Reward != nullptr)
            {
                _finishButton->setVisible(true);
            }
        }
    }

    int QuestListDialog::FindSelectedIndex()
    {
        int selectedIndex = 0;
        if (SelectedQuest != nullptr)
        {
            for (int i = 0; i < Rows.size(); i++)
            {
                if (Rows[i] == nullptr || SelectedQuest != Rows[i]->Quest)
                {
                    continue;
                }

                selectedIndex = i;
            }
        }

        return selectedIndex;
    }

    void QuestListDialog::Dispose(bool disposing)
    {
        MirImageControl::Dispose(disposing);

        Quests.clear();

        SelectedQuest = nullptr;
        Message = nullptr;
        Reward = nullptr;

        for (QuestRow *row : Rows.Where([&] (std::any row)
        {
            return row != nullptr && !row->isDisposed();
        }))
        {
            row::Dispose();
        }
    }

    QuestDetailDialog::QuestDetailDialog() : _shareButton(new MirButton();
        _shareButton->setIndex(616);
        _shareButton->setHoverIndex(617);
        _shareButton->setPressedIndex(618);
        _shareButton->setLibrary(Libraries::Title);
        _shareButton->setParent(this);
        Point tempVar(40, 436);
        _shareButton->setLocation(&tempVar);
        _shareButton->setSound(SoundList::ButtonA)), _pauseButton(new MirButton();
        _pauseButton->setIndex(270);
        _pauseButton->setHoverIndex(271);
        _pauseButton->setPressedIndex(272);
        _pauseButton->setLibrary(Libraries::Title);
        _pauseButton->setParent(this);
        Point tempVar2(120, 436);
        _pauseButton->setLocation(&tempVar2);
        _pauseButton->setSound(SoundList::ButtonA);
        _pauseButton->setVisible(false)), _cancelButton(new MirButton();
        _cancelButton->setIndex(203);
        _cancelButton->setHoverIndex(204);
        _cancelButton->setPressedIndex(205);
        _cancelButton->setLibrary(Libraries::Title);
        _cancelButton->setParent(this);
        Point tempVar3(200, 436);
        _cancelButton->setLocation(&tempVar3);
        _cancelButton->setSound(SoundList::ButtonA))
        {
        setIndex(960);
        setLibrary(Libraries::Prguse);
        setMovable(true);
        setSort(true);
        Point tempVar4(Settings::ScreenWidth / 2 + 20, 60);
        setLocation(&tempVar4);

        MirImageControl *TitleLabel = new MirImageControl();
        TitleLabel->setIndex(16);
        TitleLabel->setLibrary(Libraries::Title);
        Point tempVar5(18, 9);
        TitleLabel->setLocation(&tempVar5);
        TitleLabel->setParent(this);

        #pragma region Message Area

        MirButton *upButton = new MirButton();
        upButton->setIndex(197);
        upButton->setHoverIndex(198);
        upButton->setPressedIndex(199);
        upButton->setLibrary(Libraries::Prguse2);
        upButton->setParent(this);
        Size tempVar6(16, 14);
        upButton->setSize(&tempVar6);
        Point tempVar7(293, 33);
        upButton->setLocation(&tempVar7);
        upButton->setSound(SoundList::ButtonA);
        upButton->setVisible(true);

        MirButton *downButton = new MirButton();
        downButton->setIndex(207);
        downButton->setHoverIndex(208);
        downButton->setLibrary(Libraries::Prguse2);
        downButton->setPressedIndex(209);
        downButton->setParent(this);
        Size tempVar8(16, 14);
        downButton->setSize(&tempVar8);
        Point tempVar9(293, 280);
        downButton->setLocation(&tempVar9);
        downButton->setSound(SoundList::ButtonA);
        downButton->setVisible(true);

        MirButton *positionBar = new MirButton();
        positionBar->setIndex(205);
        positionBar->setHoverIndex(206);
        positionBar->setPressedIndex(206);
        positionBar->setLibrary(Libraries::Prguse2);
        Point tempVar10(293, 48);
        positionBar->setLocation(&tempVar10);
        positionBar->setParent(this);
        positionBar->setMovable(true);
        positionBar->setSound(SoundList::None);
        positionBar->setVisible(false);

        Message = new QuestMessage(upButton, downButton, positionBar, 16, true);
        Message->Font = new Font(Settings::FontName, 9.0F);
        Message->setParent(this);
        Size tempVar11(280, 320);
        Message->setSize(&tempVar11);
        Point tempVar12(10, 35);
        Message->setLocation(&tempVar12);
        Message->PosMinY = 46;
        Message->PosMaxY = 261;

        #pragma endregion

        #pragma region Rewards

        Reward = new QuestRewards();
        Reward->setParent(this);
        Size tempVar13(315, 130);
        Reward->setSize(&tempVar13);
        Point tempVar14(5, 307);
        Reward->setLocation(&tempVar14);

        #pragma endregion

        #pragma region Buttons

        _shareButton->Click += [&] (o, e)
        {
            C::ShareQuest *tempVar15 = new C::ShareQuest();
            tempVar15->QuestIndex = Quest->Id;
            Network::Enqueue(tempVar15);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar15' statement was not added since tempVar15 was passed to a method or constructor. Handle memory management manually.
        };


        _cancelButton->Click += [&] (o, e)
        {
            MirMessageBox *messageBox = new MirMessageBox("Are you sure you want to cancel this quest?", MirMessageBoxButtons::YesNo);
    
            messageBox->YesButton->Click += [&] (o1, a)
            {
                    C::AbandonQuest *tempVar16 = new C::AbandonQuest();
                    tempVar16->QuestIndex = Quest->Id;
                    Network::Enqueue(tempVar16);
                    Hide();

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar16' statement was not added since tempVar16 was passed to a method or constructor. Handle memory management manually.
            };
            messageBox->Show();

            delete messageBox;
        };

        #pragma endregion

        MirButton *closeButton = new MirButton();
        closeButton->setIndex(360);
        closeButton->setHoverIndex(361);
        closeButton->setPressedIndex(362);
        closeButton->setLibrary(Libraries::Prguse2);
        closeButton->setParent(this);
        Point tempVar17(289, 3);
        closeButton->setLocation(&tempVar17);
        closeButton->setSound(SoundList::ButtonA);
        closeButton->Click += [&] (o, e)
        {
            Hide();
        };

        //MirButton helpButton = new MirButton
        //{
        //    Index = 257,
        //    HoverIndex = 258,
        //    PressedIndex = 259,
        //    Library = Libraries.Prguse2,
        //    Parent = this,
        //    Location = new Point(266, 3),
        //    Sound = SoundList.ButtonA,
        //};
        //helpButton.Click += (o, e) => GameScene.Scene.HelpDialog.DisplayPage("Quests");

        delete closeButton;
//C# TO C++ CONVERTER TODO TASK: A 'delete positionBar' statement was not added since positionBar was passed to a method or constructor. Handle memory management manually.
//C# TO C++ CONVERTER TODO TASK: A 'delete downButton' statement was not added since downButton was passed to a method or constructor. Handle memory management manually.
//C# TO C++ CONVERTER TODO TASK: A 'delete upButton' statement was not added since upButton was passed to a method or constructor. Handle memory management manually.
        delete TitleLabel;
        }

    void QuestDetailDialog::DisplayQuestDetails(ClientQuestProgress *quest)
    {
        if (quest == nullptr)
        {
            return;
        }

        Quest = quest;
        Reward->UpdateRewards(Quest);
        Message->UpdateQuest(Quest);

        Show();
    }

    QuestDiaryDialog::QuestDiaryDialog()
    {
        setIndex(961);
        setLibrary(Libraries::Prguse);
        setMovable(true);
        setSort(true);
        Point tempVar(Settings::ScreenWidth / 2 - 300 - 20, 60);
        setLocation(&tempVar);

        MirImageControl *TitleLabel = new MirImageControl();
        TitleLabel->setIndex(15);
        TitleLabel->setLibrary(Libraries::Title);
        Point tempVar2(18, 9);
        TitleLabel->setLocation(&tempVar2);
        TitleLabel->setParent(this);

        _takenQuestsLabel = new MirLabel();
        Font tempVar3(Settings::FontName, 8.0F);
        _takenQuestsLabel->setFont(&tempVar3);
        _takenQuestsLabel->setParent(this);
        _takenQuestsLabel->setAutoSize(true);
        Point tempVar4(210, 7);
        _takenQuestsLabel->setLocation(&tempVar4);

        _closeButton = new MirButton();
        _closeButton->setIndex(193);
        _closeButton->setHoverIndex(194);
        _closeButton->setPressedIndex(195);
        _closeButton->setLibrary(Libraries::Title);
        _closeButton->setParent(this);
        Point tempVar5(200, 436);
        _closeButton->setLocation(&tempVar5);
        _closeButton->setSound(SoundList::ButtonA);
        _closeButton->Click += [&] (o, e)
        {
            Hide();
        };

        MirButton *closeButton = new MirButton();
        closeButton->setIndex(360);
        closeButton->setHoverIndex(361);
        closeButton->setPressedIndex(362);
        closeButton->setLibrary(Libraries::Prguse2);
        closeButton->setParent(this);
        Point tempVar6(289, 3);
        closeButton->setLocation(&tempVar6);
        closeButton->setSound(SoundList::ButtonA);
        closeButton->Click += [&] (o, e)
        {
            Hide();
        };

        delete closeButton;
        delete TitleLabel;
    }

    void QuestDiaryDialog::DisplayQuests()
    {
        ClearLog();

        Quests = GameScene::getUser()->CurrentQuests;

        _takenQuestsLabel->setText(StringHelper::formatSimple("List: {0}/{1}", Quests.size(), Globals::MaxConcurrentQuests));

        auto groupedQuests = Quests.GroupBy([&] (std::any d)
        {
            d::QuestInfo::Group;
        }).ToList();

        int nextY = 40;

        for (auto group : groupedQuests)
        {
            std::vector<ClientQuestProgress*> singleGroup = group::ToList();

            bool expanded = ExpandedGroups.size() <= 0 || std::find(ExpandedGroups.begin(), ExpandedGroups.end(), group::Key) != ExpandedGroups.end();

            QuestGroupQuestItem *groupQuest = new QuestGroupQuestItem(group.Key, singleGroup, expanded);
            groupQuest->setParent(this);
            groupQuest->setVisible(true);
            Point tempVar(15, nextY);
            groupQuest->setLocation(&tempVar);
            groupQuest->ExpandedChanged->addListener([&] (o, e)
            {
                nextY = 40;
    
                for (auto task : TaskGroups)
                {
                    Point tempVar2(15, nextY);
                    task->setLocation(&tempVar2);
                    nextY += task->SizeY;
    
                    if (task->Expanded)
                    {
                        if (!std::find(ExpandedGroups.begin(), ExpandedGroups.end(), task->Group) != ExpandedGroups.end())
                        {
                            ExpandedGroups.push_back(task->Group);
                        }
                    }
                    else
                    {
                        ExpandedGroups.Remove(task->Group);
                    }
                }
            });
            groupQuest->SelectedQuestChanged->addListener([&] (o, e)
            {
                QuestSingleQuestItem *singleQuestItem = static_cast<QuestSingleQuestItem*>(o);
    
                if (singleQuestItem == nullptr)
                {
                    return;
                }
    
                for (auto item : TaskGroups)
                {
                    item->DeselectQuests();
                }
    
                singleQuestItem->Selected = true;
            });

            nextY += groupQuest->SizeY;

            TaskGroups.push_back(groupQuest);

//C# TO C++ CONVERTER TODO TASK: A 'delete groupQuest' statement was not added since groupQuest was passed to a method or constructor. Handle memory management manually.
        }
    }

    void QuestDiaryDialog::ClearLog()
    {
        for (auto taskGroupItem : TaskGroups)
        {
            taskGroupItem->Dispose();
        }
        TaskGroups.clear();
    }

    void QuestDiaryDialog::Show()
    {
        if (getVisible())
        {
            return;
        }
        setVisible(true);

        DisplayQuests();
    }

    void QuestDiaryDialog::Toggle()
    {
        if (!getVisible())
        {
            Show();
        }
        else
        {
            Hide();
        }
    }

    void QuestDiaryDialog::Dispose(bool disposing)
    {
        MirImageControl::Dispose(disposing);

        Quests.clear();
        ClearLog();
    }

    QuestTrackingDialog::QuestTrackingDialog()
    {
        setMovable(true);
        Point tempVar(0, 100);
        setLocation(&tempVar);
        setSort(false);
        //Size = new Size(150, 50);
    }

    void QuestTrackingDialog::DisplayQuests()
    {
        for (auto label : TaskLines)
        {
            label->Dispose();
        }

        std::vector<ClientQuestProgress*> questsToTrack;

        questsToTrack.clear();

        questsToTrack.AddRange(from quest in MapObject::User->CurrentQuests from id in TrackedQuestsIds.Where([&] (std::any id)
        {
            return quest->Id == id;
        }) select quest);

        if (questsToTrack.size() < 1)
        {
            Hide();
            return;
        }

        int y = 0;

        for (int i = 0; i < questsToTrack.size(); i++)
        {
            _questNameLabel = new MirLabel();
            _questNameLabel->setText(questsToTrack[i]->QuestInfo->Name);
            _questNameLabel->setAutoSize(true);
            _questNameLabel->setBackColour(Color::Transparent);
            _questNameLabel->setFont(QuestFont);
            _questNameLabel->setForeColour(Color::LimeGreen);
            Point tempVar(5, 20 + y);
            _questNameLabel->setLocation(&tempVar);
            _questNameLabel->setOutLine(true);
            _questNameLabel->setParent(this);
            _questNameLabel->setVisible(true);

            TaskLines.push_back(_questNameLabel);

            for (auto questToTrack : questsToTrack[i]->TaskList)
            {
                y += 15;

                std::string trackedQuest = questToTrack;

                _questTaskLabel = new MirLabel();
                _questTaskLabel->setText(trackedQuest);
                _questTaskLabel->setAutoSize(true);
                _questTaskLabel->setBackColour(Color::Transparent);
                _questTaskLabel->setFont(QuestFont);
                _questTaskLabel->setForeColour(Color::White);
                Point tempVar2(25, 20 + y);
                _questTaskLabel->setLocation(&tempVar2);
                _questTaskLabel->setOutLine(true);
                _questTaskLabel->setParent(this);
                _questTaskLabel->setVisible(true);

                TaskLines.push_back(_questTaskLabel);
            }

            if (i >= 5)
            {
                break;
            }

            y += 30;
        }

        Show();
    }

    void QuestTrackingDialog::AddQuest(ClientQuestProgress *quest, bool New)
    {
        if (TrackedQuestsIds.Any([&] (std::any d)
        {
            return d == quest->Id;
        }) || TrackedQuestsIds.size() >= 5)
        {
            return;
        }

        TrackedQuestsIds.push_back(quest->Id);

        DisplayQuests();
        if (!New)
        {
            UpdateTrackedQuests();
        }
    }

    void QuestTrackingDialog::RemoveQuest(ClientQuestProgress *quest)
    {
        TrackedQuestsIds.Remove(quest->Id);

        DisplayQuests();
        UpdateTrackedQuests();
    }

    void QuestTrackingDialog::UpdateTrackedQuests()
    {
        for (int j = 0; j < Settings::TrackedQuests.size(); j++)
        {
            if (TrackedQuestsIds.size() > 0 && j < TrackedQuestsIds.size())
            {
                Settings::TrackedQuests[j] = TrackedQuestsIds[j];
                continue;
            }
            Settings::TrackedQuests[j] = -1;
        }

        Settings::SaveTrackedQuests(GameScene::getUser()->Name);
    }

    QuestRow::QuestRow()
    {
        setSound(SoundList::ButtonA);
        Size tempVar(200, 17);
        setSize(&tempVar);

        BeforeDraw += QuestRow_BeforeDraw;

        SelectedImage = new MirImageControl();
        SelectedImage->setIndex(956);
        SelectedImage->setLibrary(Libraries::Prguse);
        Point tempVar2(25, 0);
        SelectedImage->setLocation(&tempVar2);
        SelectedImage->setParent(this);
        SelectedImage->setVisible(false);

        IconImage = new MirImageControl();
        IconImage->setIndex(0);
        IconImage->setLibrary(Libraries::Prguse);
        Point tempVar3(3, 0);
        IconImage->setLocation(&tempVar3);
        IconImage->setParent(this);
        IconImage->setVisible(false);

        RequirementLabel = new MirLabel();
        Point tempVar4(20, 0);
        RequirementLabel->setLocation(&tempVar4);
        Size tempVar5(178, 17);
        RequirementLabel->setSize(&tempVar5);
        RequirementLabel->setDrawFormat(TextFormatFlags::VerticalCenter);
        RequirementLabel->setParent(this);
        RequirementLabel->setNotControl(true);

        NameLabel = new MirLabel();
        Point tempVar6(60, 0);
        NameLabel->setLocation(&tempVar6);
        Size tempVar7(140, 17);
        NameLabel->setSize(&tempVar7);
        NameLabel->setDrawFormat(TextFormatFlags::VerticalCenter);
        NameLabel->setParent(this);
        NameLabel->setNotControl(true);

        UpdateInterface();
    }

    void QuestRow::QuestRow_BeforeDraw(std::any sender, EventArgs *e)
    {
        UpdateInterface();
    }

    void QuestRow::UpdateInterface()
    {
        if (Quest == nullptr)
        {
            return;
        }

        int iconTypeOffset = static_cast<int>(Quest->getIcon()) > 3 ? 15 : 0;

        IconImage->setIndex(961 + static_cast<int>(Quest->getIcon()) + iconTypeOffset);
        IconImage->setVisible(true);

        NameLabel->setText(Quest->QuestInfo->Name);
        RequirementLabel->setText(Quest->QuestInfo->MinLevelNeeded > 0 ? "Lv " + std::to_string(Quest->QuestInfo->MinLevelNeeded) : "");

        SelectedImage->setVisible(Selected);
    }

    void QuestRow::Dispose(bool disposing)
    {
        MirControl::Dispose(disposing);

        Quest = nullptr;
        NameLabel = nullptr;
        RequirementLabel = nullptr;
        SelectedImage = nullptr;
        IconImage = nullptr;

        Selected = false;
    }

Regex *const QuestMessage::C = new Regex(R"({(.*?/.*?)})");
const std::string TaskTitle, QuestMessage::ProgressTitle = "Progress";

    QuestMessage::QuestMessage(MirButton *scrollUpButton, MirButton *scrollDownButton, MirButton *positionBar, int lineCount, bool displayProgress) : _textLabel(std::vector<MirLabel*>(LineCount))
    {
        ScrollUpButton = scrollUpButton;
        ScrollDownButton = scrollDownButton;
        PositionBar = positionBar;
        DisplayProgress = displayProgress;

        MouseWheel += QuestMessage_MouseWheel;
        PositionBar->OnMoving->addListener("PositionBar_OnMoving", std::bind(&QuestMessage::PositionBar_OnMoving, this, std::placeholders::_1, std::placeholders::_2));

        LineCount = lineCount;

        PosX = PositionBar->getLocation()->X;
        PosMinY = PositionBar->getLocation()->Y;
        PosMaxY = PositionBar->getLocation()->Y;

        ScrollUpButton->Click += [&] (o, e)
        {
            if (TopLine <= 0)
            {
                return;
            }
    
            TopLine--;
    
            NewText(CurrentLines, false);
            UpdatePositionBar();
        };

        ScrollDownButton->Click += [&] (o, e)
        {
            if (TopLine + LineCount >= CurrentLines.size())
            {
                return;
            }
    
            TopLine++;
    
            NewText(CurrentLines, false);
            UpdatePositionBar();
        };

        AfterDraw += QuestMessage_AfterDraw;
    }

    void QuestMessage::QuestMessage_AfterDraw(std::any sender, EventArgs *e)
    {
        if (Quest == nullptr || CurrentLines.size() < 1)
        {
            return;
        }

        int adjust = 0;

        for (int i = TopLine; i < BottomLine; i++)
        {
            if (i != 0 && CurrentLines[i] != TaskTitle && CurrentLines[i] != ProgressTitle)
            {
                continue;
            }

            Point tempVar(getDisplayLocation()->X + 5, getDisplayLocation()->Y + 5 + (i - TopLine) * 15 + adjust);
            Libraries::Prguse->Draw(919, &tempVar, Color::White);

            adjust += 5;
        }
    }

    void QuestMessage::QuestMessage_MouseWheel(std::any sender, MouseEventArgs *e)
    {
        int count = e->Delta / SystemInformation::MouseWheelScrollDelta;

        if (TopLine == 0 && count >= 0)
        {
            return;
        }
        if (TopLine == CurrentLines.size() - 1 && count <= 0)
        {
            return;
        }
        if (CurrentLines.size() <= LineCount)
        {
            return;
        }

        TopLine -= count;

        if (TopLine < 0)
        {
            TopLine = 0;
        }
        if (TopLine + LineCount > CurrentLines.size() - 1)
        {
            TopLine = CurrentLines.size() - LineCount;
        }

        NewText(CurrentLines, false);

        UpdatePositionBar();
    }

    void QuestMessage::PositionBar_OnMoving(std::any sender, MouseEventArgs *e)
    {
        int x = PosX;
        int y = PositionBar->getLocation()->Y;

        if (y >= PosMaxY)
        {
            y = PosMaxY;
        }
        if (y <= PosMinY)
        {
            y = PosMinY;
        }

        int location = y - PosMinY;
        int interval = (PosMaxY - PosMinY) / (CurrentLines.size() - LineCount);

        double yPoint = static_cast<double>(location) / interval;

        TopLine = static_cast<short>(std::floor(yPoint));

        Point tempVar(x, y);
        PositionBar->setLocation(&tempVar);

        NewText(CurrentLines, false);
    }

    void QuestMessage::UpdatePositionBar()
    {
        if (CurrentLines.size() <= LineCount)
        {
            PositionBar->setVisible(false);
            return;
        }

        PositionBar->setVisible(true);

        int interval = (PosMaxY - PosMinY) / (CurrentLines.size() - LineCount);

        int x = PosX;
        int y = PosMinY + (TopLine * interval);

        if (y >= PosMaxY)
        {
            y = PosMaxY;
        }
        if (y <= PosMinY)
        {
            y = PosMinY;
        }


        Point tempVar(x, y);
        PositionBar->setLocation(&tempVar);
    }

    void QuestMessage::UpdateQuest(ClientQuestProgress *quest)
    {
        Quest = quest;

        CurrentLines.clear();

        //add quest title at the beginning
        CurrentLines.Insert(0, Quest->QuestInfo->Name);

        if (Quest->Taken && !Quest->QuestInfo->getSameFinishNPC() && Quest->QuestInfo->CompletionDescription.size() > 0 && GameScene::Scene->QuestListDialog->CurrentNPCID == Quest->QuestInfo->FinishNPCIndex)
        {
            for (auto line : *Quest->QuestInfo->CompletionDescription)
            {
                CurrentLines.push_back(line);
            }
        }
        else
        {
            for (auto line : *Quest->QuestInfo->Description)
            {
                CurrentLines.push_back(line);
            }

            AdjustDescription();
        }

        NewText(CurrentLines);
    }

    void QuestMessage::AdjustDescription()
    {
        if (Quest->QuestInfo->TaskDescription.size() > 0)
        {
            CurrentLines.push_back(" ");

            CurrentLines.push_back(TaskTitle);

            for (auto task : *Quest->QuestInfo->TaskDescription)
            {
                CurrentLines.push_back(task);
            }
        }

        if (Quest->Taken && Quest->TaskList.size() > 0 && DisplayProgress)
        {
            CurrentLines.push_back(" ");

            CurrentLines.push_back(ProgressTitle);

            for (auto task : *Quest->TaskList)
            {
                CurrentLines.push_back(task);
            }
        }
    }

    void QuestMessage::NewText(std::vector<std::string> &lines, bool resetIndex)
    {
        if (resetIndex)
        {
            TopLine = 0;
            CurrentLines = lines;
            UpdatePositionBar();
        }

        for (MirLabel *t : _textButtons.Where([&] (std::any t)
        {
            return t != nullptr;
        }))
        {
            t::Dispose();
        }

        for (MirLabel *t : _textLabel.Where([&] (std::any t)
        {
            return t != nullptr;
        }))
        {
            t->Text = "";
        }

        _textButtons.clear();

        int adjust = 0;

        BottomLine = lines.size() > LineCount ? ((LineCount + TopLine) > lines.size() ? lines.size() : (LineCount + TopLine)) : lines.size();

        for (int i = TopLine; i < BottomLine; i++)
        {
            Font *font = Font;
            Color *fontColor = Color::White;
            bool title = false;

            if (i == 0 || lines[i] == TaskTitle || lines[i] == ProgressTitle)
            {
                font = new Font(Settings::FontName, 10.0F, FontStyle::Bold);
                title = true;

                if (i == 0)
                {
                    fontColor = Color::Yellow;
                }
            }

            MirLabel *tempVar = new MirLabel();
            tempVar->setFont(font);
            tempVar->setForeColour(fontColor);
            tempVar->setDrawFormat(TextFormatFlags::WordBreak);
            tempVar->setVisible(true);
            tempVar->setParent(this);
            Size tempVar2(getSize()->Width, 20);
            tempVar->setSize(&tempVar2);
            Point tempVar3(title ? 15 : 0, 0 + (i - TopLine) * 15 + adjust);
            tempVar->setLocation(&tempVar3);
            tempVar->setNotControl(true);
            _textLabel[i - TopLine] = tempVar;

            if (title)
            {
                adjust += 5;
            }

            if (i >= lines.size())
            {
                _textLabel[i - TopLine]->setText("");

                delete tempVar;
//C# TO C++ CONVERTER TODO TASK: A 'delete font' statement was not added since font was assigned to another object. Handle memory management manually.
                continue;
            }

            std::string currentLine = lines[i];

            std::vector<Match*> matchList = C->Matches(currentLine)->Cast<Match*>().ToList();

            int oldLength = currentLine.length();

            for (auto match : matchList.OrderBy([&] (std::any o)
            {
                return o::Index;
            }).ToList())
            {
                int offSet = oldLength - currentLine.length();

                Capture *capture = match::Groups[1].Captures[0];
                std::vector<std::string> values = StringHelper::split(capture->Value, '/');
//C# TO C++ CONVERTER TODO TASK: There is no C++ equivalent to the .NET String 'Insert' method unless assigning to the string instance:
                currentLine.erase(capture->Index - 1 - offSet, capture->Length + 2)->Insert(capture->Index - 1 - offSet, values[0]);
                std::string text = currentLine.substr(0, capture->Index - 1 - offSet) + " ";
                Size *size = TextRenderer::MeasureText(CMain::Graphics, text, _textLabel[i - TopLine]->getFont(), _textLabel[i - TopLine]->getSize(), TextFormatFlags::TextBoxControl);

                if (C->Match(match->Value)->Success)
                {
                    Point tempVar4(size->Width - 10, 0);
                    NewColour(values[0], values[1], Functions::Add(_textLabel[i - TopLine]->getLocation(), &tempVar4));
                }
            }

            _textLabel[i - TopLine]->setText(currentLine);
            _textLabel[i - TopLine]->MouseWheel += QuestMessage_MouseWheel;

            delete tempVar;
//C# TO C++ CONVERTER TODO TASK: A 'delete font' statement was not added since font was assigned to another object. Handle memory management manually.
        }
    }

    void QuestMessage::NewColour(const std::string &text, const std::string &colour, Point *p)
    {
        Color *textColour = Color::FromName(colour);

        MirLabel *temp = new MirLabel();
        temp->setAutoSize(true);
        temp->setVisible(true);
        temp->setParent(this);
        temp->setLocation(p);
        temp->setText(text);
        temp->setForeColour(textColour);
        temp->setFont(Font);
        temp->MouseWheel += QuestMessage_MouseWheel;

        _textButtons.push_back(temp);

//C# TO C++ CONVERTER TODO TASK: A 'delete temp' statement was not added since temp was passed to a method or constructor. Handle memory management manually.
    }

    void QuestMessage::Dispose(bool disposing)
    {
        MirControl::Dispose(disposing);

        Quest = nullptr;
        ScrollUpButton = nullptr;
        ScrollDownButton = nullptr;
        PositionBar = nullptr;

        CurrentLines.clear();
    }

std::vector<QuestCell*> QuestRewards::FixedItems(5);
std::vector<QuestCell*> QuestRewards::SelectItems(5);

    QuestRewards::QuestRewards() : _goldLabel(new MirLabel();
        Size tempVar(75, 20);
        _goldLabel->setSize(&tempVar);
        _goldLabel->setParent(this)), _expLabel(new MirLabel();
        Size tempVar2(75, 20);
        _expLabel->setSize(&tempVar2);
        Point tempVar3(40, 0);
        _expLabel->setLocation(&tempVar3);
        _expLabel->setParent(this)), _creditLabel(new MirLabel();
        Size tempVar4(75, 20);
        _creditLabel->setSize(&tempVar4);
        Point tempVar5(60, 0);
        _creditLabel->setLocation(&tempVar5);
        _creditLabel->setParent(this))
        {



        BeforeDraw += QuestReward_BeforeDraw;
        }

    void QuestRewards::UpdateRewards(ClientQuestProgress *quest)
    {
        Quest = quest;

        CleanRewards();
        UpdateInterface();
        Redraw();
    }

    void QuestRewards::QuestReward_BeforeDraw(std::any sender, EventArgs *e)
    {

        if (Quest == nullptr)
        {
            return;
        }

        ClientQuestInfo *quest = Quest->QuestInfo;

        int goldXOffset = 0;
        int creditXOffset = 0;

        if (quest->RewardExp > 0)
        {
            Libraries::Prguse->Draw(966, getDisplayLocation()->X + 10, getDisplayLocation()->Y + 2);
        }
        else
        {
            goldXOffset = -90;
            creditXOffset -= 90;
        }


        if (quest->RewardGold > 0)
        {
            Libraries::Prguse->Draw(965, getDisplayLocation()->X + 100 + goldXOffset, getDisplayLocation()->Y + 2);
        }
        else
        {
            creditXOffset -= 90;
        }

        if (quest->RewardCredit > 0)
        {
            Libraries::Prguse->Draw(2447, getDisplayLocation()->X + 190 + creditXOffset, getDisplayLocation()->Y + 2);
        }

        Libraries::Title->Draw(17, getDisplayLocation()->X + 20, getDisplayLocation()->Y + 66);
    }

    void QuestRewards::CleanRewards()
    {
        for (QuestCell *item : SelectItems.Where([&] (std::any item)
        {
            return item != nullptr;
        }))
        {
            item::Dispose();
        }

        for (QuestCell *item : FixedItems.Where([&] (std::any item)
        {
            return item != nullptr;
        }))
        {
            item::Dispose();
        }

        SelectedItemIndex = -1;
        SelectedItem = nullptr;
    }

    void QuestRewards::UpdateInterface()
    {
        ClientQuestInfo *quest = Quest->QuestInfo;

        _goldLabel->setVisible(false);
        _expLabel->setVisible(false);
        _creditLabel->setVisible(false);

        int goldXOffset = 0;
        int creditXOffset = 0;

        if (quest->RewardExp > 0)
        {
            _expLabel->setText(std::to_string(quest->RewardExp));
            _expLabel->setVisible(true);
        }
        else
        {
            goldXOffset = -90;
            creditXOffset -= 90;
        }

        if (quest->RewardGold > 0)
        {
            _goldLabel->setText(std::to_string(quest->RewardGold));
            Point tempVar(120 + goldXOffset, 0);
            _goldLabel->setLocation(&tempVar);
            _goldLabel->setVisible(true);
        }
        else
        {
            creditXOffset -= 90;
        }

        if (quest->RewardCredit > 0)
        {
            _creditLabel->setText(std::to_string(quest->RewardCredit));
            Point tempVar2(210 + creditXOffset, 0);
            _creditLabel->setLocation(&tempVar2);
            _creditLabel->setVisible(true);
        }


        if (quest->RewardsFixedItem.size() > 0)
        {
            //var fixedRewards = FilterRewards(quest.RewardsFixedItem);

            for (int i = 0; i < FixedItems.size(); i++)
            {
                if (i >= quest->RewardsFixedItem.size())
                {
                    break;
                }

                QuestCell *tempVar3 = new QuestCell();
                tempVar3->Item = quest->RewardsFixedItem[i]->Item;
                tempVar3->Count = quest->RewardsFixedItem[i]->Count;
                tempVar3->setParent(this);
                Point tempVar4(i * 45 + 15, 24);
                tempVar3->setLocation(&tempVar4);
                tempVar3->Fixed = true;
                FixedItems[i] = tempVar3;

                delete tempVar3;
            }
        }

        if (quest->RewardsSelectItem.size() > 0)
        {
            auto selRewards = FilterRewards(quest->RewardsSelectItem);

            for (int i = 0; i < SelectItems.size(); i++)
            {
                if (i >= selRewards.size())
                {
                    break;
                }

                QuestCell *tempVar5 = new QuestCell();
                tempVar5->Item = selRewards[i]->Item;
                tempVar5->Count = selRewards[i]->Count;
                tempVar5->setParent(this);
                Point tempVar6(i * 45 + 15, 89);
                tempVar5->setLocation(&tempVar6);
                SelectItems[i] = tempVar5;
                SelectItems[i]->Click += [&] (o, e)
                {
                    for (auto itm : SelectItems)
                    {
                        if (itm == nullptr)
                        {
                            continue;
                        }
    
                        if (itm == o)
                        {
                            itm->Selected = true;
                            SelectedItem = itm->Item;
                            SelectedItemIndex = FindSelectedItemIndex();
                        }
                        else
                        {
                            itm->Selected = false;
                        }
                    }
    
                    Redraw();
                };

                delete tempVar5;
            }
        }
    }

    std::vector<QuestItemReward*> QuestRewards::FilterRewards(std::vector<QuestItemReward*> &rewardItems)
    {
        std::vector<QuestItemReward*> filteredRewards;

        //Only display same sex items
        for (auto reward : rewardItems)
        {
            ItemInfo *item = reward->Item;

            switch (MapObject::User->Gender)
            {
                case MirGender::Male:
                    if (!item->RequiredGender::HasFlag(RequiredGender::Male))
                    {
                        continue;
                    }
                    break;
                case MirGender::Female:
                    if (!item->RequiredGender::HasFlag(RequiredGender::Female))
                    {
                        continue;
                    }
                    break;
            }

            filteredRewards.push_back(reward);
        }

        return filteredRewards;
    }

    int QuestRewards::FindSelectedItemIndex()
    {
        int selectedItemIndex = 0;
        if (SelectedItem == nullptr)
        {
            return selectedItemIndex;
        }

        for (int i = 0; i < Quest->QuestInfo->RewardsSelectItem.size(); i++)
        {
            ItemInfo *item = Quest->QuestInfo->RewardsSelectItem[i]->Item;

            if (item == nullptr || SelectedItem != item)
            {
                continue;
            }

            selectedItemIndex = i;
        }

        return selectedItemIndex;
    }

    void QuestRewards::Dispose(bool disposing)
    {
        MirControl::Dispose(disposing);

        Quest = nullptr;

        for (QuestCell *cell : FixedItems.Where([&] (std::any cell)
        {
            return cell != nullptr && !cell->isDisposed();
        }))
        {
            cell::Dispose();
        }

        for (QuestCell *cell : SelectItems.Where([&] (std::any cell)
        {
            return cell != nullptr && !cell->isDisposed();
        }))
        {
            cell::Dispose();
        }
    }

    MirLabel *QuestCell::getCountLabel() const
    {
        return CountLabel;
    }

    void QuestCell::setCountLabel(MirLabel *value)
    {
        CountLabel = value;
    }

    QuestCell::QuestCell()
    {
        Size tempVar(32, 32);
        setSize(&tempVar);
    }

    void QuestCell::OnMouseEnter()
    {
        MirControl::OnMouseEnter();

        if (ShowItem == nullptr)
        {
            ShowItem = new UserItem(Item);
            ShowItem->MaxDura = Item->Durability;
            ShowItem->CurrentDura = Item->Durability;
        }

        GameScene::Scene->CreateItemLabel(ShowItem);
    }

    void QuestCell::OnMouseLeave()
    {
        MirControl::OnMouseLeave();
        GameScene::Scene->DisposeItemLabel();
        GameScene::HoverItem = nullptr;
        ShowItem = nullptr;
    }

    void QuestCell::DrawControl()
    {
        if (Item == nullptr)
        {
            return;
        }

        Size *size = Libraries::Items->GetTrueSize(Item->Image);
        Point *offSet = new Point((40 - size->Width) / 2, (32 - size->Height) / 2);

        CreateDisposeLabel();

        if (Fixed)
        {
            Libraries::Prguse->Draw(989, getDisplayLocation()->X, getDisplayLocation()->Y - 1);
        }
        else if (Selected)
        {
            Libraries::Prguse->Draw(979, getDisplayLocation()->X, getDisplayLocation()->Y - 5);
        }

        Libraries::Items->Draw(Item->Image, offSet->X + getDisplayLocation()->X, offSet->Y + getDisplayLocation()->Y);

        delete offSet;
    }

    void QuestCell::Dispose(bool disposing)
    {
        MirControl::Dispose(disposing);

        Item = nullptr;
        ShowItem = nullptr;

        DisposeCountLabel();
    }

    void QuestCell::CreateDisposeLabel()
    {
        if (Count <= 1)
        {
            DisposeCountLabel();
            return;
        }

        if (getCountLabel() == nullptr || getCountLabel()->isDisposed())
        {
            MirLabel tempVar();
            setCountLabel(&tempVar);
            getCountLabel()->setAutoSize(true);
            getCountLabel()->setForeColour(Color::Yellow);
            getCountLabel()->setNotControl(true);
            getCountLabel()->setOutLine(false);
            getCountLabel()->setParent(this);
        }

//C# TO C++ CONVERTER TODO TASK: There is no C++ equivalent to 'ToString':
        getCountLabel()->setText(Count.ToString("###0"));
        Point tempVar2(getSize()->Width - getCountLabel()->getSize()->Width + 8, getSize()->Height - getCountLabel()->getSize()->Height);
        getCountLabel()->setLocation(&tempVar2);
    }

    void QuestCell::DisposeCountLabel()
    {
        if (getCountLabel() != nullptr && !getCountLabel()->isDisposed())
        {
            getCountLabel()->Dispose();
        }
        setCountLabel(nullptr);
    }

    void QuestGroupQuestItem::OnExpandedChanged()
    {
        if (ExpandedChanged != nullptr)
        {
            ExpandedChanged::Invoke(this, EventArgs::Empty);
        }
    }

    void QuestGroupQuestItem::OnSelectedQuestChanged(std::any ob)
    {
        if (SelectedQuestChanged != nullptr)
        {
            SelectedQuestChanged::Invoke(ob, EventArgs::Empty);
        }
    }

    QuestGroupQuestItem::QuestGroupQuestItem(const std::string &group, std::vector<ClientQuestProgress*> &quests, bool expanded) : _expandButton(new MirButton();
        _expandButton->setIndex(Expanded ? 917 : 918);
        _expandButton->setLibrary(Libraries::Prguse);
        _expandButton->setParent(this);
        Size tempVar(16, 14);
        _expandButton->setSize(&tempVar);
        Point tempVar2(0, 0);
        _expandButton->setLocation(&tempVar2);
        _expandButton->setSound(SoundList::ButtonA)), _groupLabel(new MirLabel();
        _groupLabel->setText(Group);
        _groupLabel->setAutoSize(true);
        _groupLabel->setParent(this);
        Font tempVar3(Settings::FontName, 8.0F);
        _groupLabel->setFont(&tempVar3);
        _groupLabel->setForeColour(Color::LimeGreen);
        Point tempVar4(18, 0);
        _groupLabel->setLocation(&tempVar4);
        _groupLabel->setVisible(true))
        {
        Group = group;
        Quests = quests;
        Expanded = expanded;

        _expandButton->Click += [&] (o, e)
        {
            ChangeExpand();
        };


        for (int i = 0; i < Quests.size(); i++)
        {
            bool Track = Settings::TrackedQuests.Contains(Quests[i]->Id) ? true : false;
            QuestSingleQuestItem *singleQuest = new QuestSingleQuestItem(Quests[i]);
            singleQuest->setParent(this);
            Point tempVar5(18, (15 * (i + 1)));
            singleQuest->setLocation(&tempVar5);
            Size tempVar6(280, 15);
            singleQuest->setSize(&tempVar6);
            singleQuest->setVisible(Expanded);
            singleQuest->SelectedQuestChanged->addListener([&] (o, e)
            {
                OnSelectedQuestChanged(o);
            });

            _tasks.push_back(singleQuest);

            if (Expanded)
            {
                SizeY += 15;
            }

//C# TO C++ CONVERTER TODO TASK: A 'delete singleQuest' statement was not added since singleQuest was passed to a method or constructor. Handle memory management manually.
        }

        Size tempVar7(280, SizeY);
        setSize(&tempVar7);
        }

    void QuestGroupQuestItem::UpdatePositions()
    {
        SizeY = 15;

        for (auto singleTask : _tasks)
        {
            singleTask->setVisible(Expanded);

            if (Expanded)
            {
                SizeY += 15;
            }
        }

        Size tempVar(280, SizeY);
        setSize(&tempVar);
    }

    void QuestGroupQuestItem::ClearTasks()
    {
        for (auto task : _tasks)
        {
            task->Dispose();
        }
        _tasks.clear();
    }

    void QuestGroupQuestItem::DeselectQuests()
    {
        for (auto task : _tasks)
        {
            task->Selected = false;
        }
    }

    void QuestGroupQuestItem::ChangeExpand()
    {
        Expanded = !Expanded;

        _expandButton->setIndex(Expanded ? 917 : 918);

        UpdatePositions();

        OnExpandedChanged();
    }

    void QuestGroupQuestItem::Dispose(bool disposing)
    {
        MirControl::Dispose(disposing);

        Group = "";
        Quests.clear();

        _expandButton->Dispose();
        _groupLabel->Dispose();

        ClearTasks();
    }

    void QuestSingleQuestItem::OnSelectedQuestChanged()
    {
        if (SelectedQuestChanged != nullptr)
        {
            SelectedQuestChanged::Invoke(this, EventArgs::Empty);
        }
    }

    QuestSingleQuestItem::QuestSingleQuestItem(ClientQuestProgress *quest) : _selectedImage(new MirImageControl();
        _selectedImage->setIndex(956);
        _selectedImage->setLibrary(Libraries::Prguse);
        Point tempVar(-10, 0);
        _selectedImage->setLocation(&tempVar);
        _selectedImage->setParent(this);
        _selectedImage->setVisible(false))
        {
        Quest = quest;
        Size tempVar2(250, 15);
        setSize(&tempVar2);
        TrackQuest = std::find(GameScene::Scene->QuestTrackingDialog->TrackedQuestsIds.begin(), GameScene::Scene->QuestTrackingDialog->TrackedQuestsIds.end(), quest->Id) != GameScene::Scene->QuestTrackingDialog->TrackedQuestsIds.end();

        std::string name = Quest->QuestInfo->Name;
        std::string level = StringHelper::formatSimple("Lv{0}", Quest->QuestInfo->MinLevelNeeded);
        std::string state = quest->Completed ? "(Complete)" : "(In Progress)";

        bool lowLevelQuest = (MapObject::User->Level - quest->QuestInfo->MinLevelNeeded) > 10;

        BeforeDraw += QuestTaskSingleItem_BeforeDraw;
        AfterDraw += QuestTaskSingleItem_AfterDraw;


        _questLabel = new MirLabel();
        _questLabel->setText(std::string::Format("{0,-4} {1}", level, name));
        _questLabel->setAutoSize(true);
        Font tempVar3(Settings::FontName, 8.0F);
        _questLabel->setFont(&tempVar3);
        _questLabel->setForeColour(lowLevelQuest ? Color::Gray : quest->New ? Color::Yellow : Color::White);
        _questLabel->setParent(this);
        Point tempVar4(0, 0);
        _questLabel->setLocation(&tempVar4);
        _questLabel->setSound(SoundList::ButtonA);

        _questLabel->Click += [&] (o, e)
        {
            MouseEventArgs *me = dynamic_cast<MouseEventArgs*>(e);
    
            if (me == nullptr)
            {
                return;
            }
    
            switch (me->Button)
            {
                case MouseButtons->Left:
                    GameScene::Scene->QuestDetailDialog->DisplayQuestDetails(Quest);
                    break;
                case MouseButtons::Right:
                {
                        if (TrackQuest)
                        {
                            GameScene::Scene->QuestTrackingDialog->RemoveQuest(Quest);
                        }
                        else
                        {
                            if (GameScene::Scene->QuestTrackingDialog->TrackedQuestsIds.size() >= 5)
                            {
                                return;
                            }
    
                            GameScene::Scene->QuestTrackingDialog->AddQuest(Quest);
                        }
    
                        TrackQuest = !TrackQuest;
                }
                    break;
            }
    
            OnSelectedQuestChanged();
        };

        _stateLabel = new MirLabel();
        _stateLabel->setText(StringHelper::formatSimple("{0}", state));
        _stateLabel->setAutoSize(true);
        Font tempVar5(Settings::FontName, 8.0F);
        _stateLabel->setFont(&tempVar5);
        _stateLabel->setForeColour(lowLevelQuest ? Color::Gray : quest->New ? Color::Yellow : Color::White);
        _stateLabel->setParent(this);
        Point tempVar6(185, 0);
        _stateLabel->setLocation(&tempVar6);
        _stateLabel->setSound(SoundList::ButtonA);
        }

    void QuestSingleQuestItem::QuestTaskSingleItem_BeforeDraw(std::any sender, EventArgs *e)
    {
        _selectedImage->setVisible(Selected);
    }

    void QuestSingleQuestItem::QuestTaskSingleItem_AfterDraw(std::any sender, EventArgs *e)
    {
        if (TrackQuest)
        {
            Point tempVar(getDisplayLocation()->X - 15, getDisplayLocation()->Y);
            Libraries::Prguse->Draw(997, &tempVar, Color::White);
        }
    }

    void QuestSingleQuestItem::Dispose(bool disposing)
    {
        MirControl::Dispose(disposing);

        Quest = nullptr;
        _questLabel->Dispose();
        _questLabel = nullptr;
    }
}
